import frappe
from frappe import _
from frappe.utils import cint, flt, cstr
from frappe.database.schema import DBTable, DbColumn
from frappe.database.schema import get_definition

class DmTable(DBTable):
    """达梦数据库表结构实现"""
    
    def create(self):
        """创建表"""
        varchar_len = frappe.db.VARCHAR_LEN
        name_column = f"`name` varchar({varchar_len}) primary key"

        additional_definitions = []
        # 列定义
        column_defs = self.get_column_definitions()
        if column_defs:
            additional_definitions.extend(column_defs)

        # 子表列
        if self.meta.get("istable") or 0:
            additional_definitions.extend([
                f"`parent` varchar({varchar_len})",
                f"`parentfield` varchar({varchar_len})",
                f"`parenttype` varchar({varchar_len})"
            ])

        # 创建序列
        if not self.meta.issingle and self.meta.autoname == "autoincrement":
            frappe.db.create_sequence(self.doctype, check_not_exists=True)
            name_column = "`name` bigint primary key"

        additional_definitions = ",\n".join(additional_definitions)

        # 创建表
        query = f"""create table "{self.table_name}" (
            {name_column},
            `creation` timestamp(6),
            `modified` timestamp(6),
            `modified_by` varchar({varchar_len}),
            `owner` varchar({varchar_len}),
            `docstatus` smallint not null default 0,
            `idx` bigint not null default 0,
            {additional_definitions}
        )"""

        frappe.db.sql_ddl(query)
        self.create_indexes()
        frappe.db.commit()

    def create_indexes(self):
        """创建索引"""
        create_index_query = ""
        for col in self.columns.values():
            if (
                col.set_index 
                and col.fieldtype in frappe.db.type_map
                and frappe.db.type_map.get(col.fieldtype)[0] not in ("text", "longtext")
            ):
                create_index_query = f'CREATE INDEX IF NOT EXISTS "{col.fieldname}" ON "{self.table_name}"("{col.fieldname}");'
                frappe.db.sql(create_index_query)


    def alter(self):
        """达梦数据库的表结构修改"""
        for col in self.columns.values():
            col.build_for_alter_table(self.current_columns.get(col.fieldname.lower()))

        # 添加列
        for col in self.add_column:
            command = f'ADD COLUMN IF NOT EXISTS "{col.fieldname}" {col.get_definition()}'
            try:
                frappe.db.alter_table(self.doctype, [command])
            except Exception as e:
                if frappe.db.is_duplicate_fieldname(e):
                    continue
                raise

        # 修改列类型和默认值
        columns_to_modify = set(self.change_type + self.set_default)
        for col in columns_to_modify:
            commands = []
            
            # 修改列类型
            if col in self.change_type:
                commands.append(f'MODIFY "{col.fieldname}" {col.get_definition(for_modification=True)}')
            
            # 设置默认值
            if col in self.set_default:
                if col.default is None:
                    commands.append(f'ALTER COLUMN "{col.fieldname}" DROP DEFAULT')
                else:
                    if col.fieldtype in ("Check", "Int"):
                        default_value = cint(col.default)
                    elif col.fieldtype in ("Currency", "Float", "Percent"):
                        default_value = flt(col.default)
                    elif not col.default:
                        default_value = "NULL"
                    else:
                        default_value = f"'{col.default}'"
                    commands.append(f'ALTER COLUMN "{col.fieldname}" SET DEFAULT {default_value}')

            # 执行修改命令
            for command in commands:
                try:
                    frappe.db.alter_table(self.doctype, [command])
                except Exception as e:
                    if frappe.db.is_duplicate_fieldname(e):
                        continue
                    raise

        # 添加索引
        for col in self.add_index:
            if not frappe.db.get_column_index(self.table_name, col.fieldname, unique=False):
                try:
                    frappe.db.sql(
                        f'CREATE INDEX "{self.table_name}_{col.fieldname}_IDX" ON "{self.table_name}"("{col.fieldname}")'
                    )
                except Exception as e:
                    if frappe.db.is_duplicate_fieldname(e):
                        continue
                    raise

        # 添加唯一索引
        for col in self.add_unique:
            try:
                frappe.db.sql(
                    f'CREATE UNIQUE INDEX "{self.table_name}_{col.fieldname}_UNQ" ON "{self.table_name}"("{col.fieldname}")'
                )
            except Exception as e:
                if frappe.db.is_duplicate_fieldname(e):
                    continue
                elif "non-unique existing values" in str(e):
                    frappe.throw(
                        _("Column {0} cannot be set as unique in {1}, as there are duplicate values").format(
                            col.fieldname, self.table_name
                        )
                    )
                raise

        # 删除索引
        for col in self.drop_index:
            if col.fieldname != "name":  # 不删除主键索引
                index_record = frappe.db.get_column_index(self.table_name, col.fieldname, unique=False)
                if index_record:
                    try:
                        frappe.db.sql_ddl(f'DROP INDEX IF EXISTS "{index_record.Key_name}"')
                    except Exception as e:
                        if frappe.db.is_duplicate_fieldname(e):
                            continue
                        raise

        # 删除唯一索引
        for col in self.drop_unique:
            if col.fieldname != "name":  # 不删除主键索引
                unique_index = frappe.db.get_column_index(self.table_name, col.fieldname, unique=True)
                if unique_index:
                    try:
                        frappe.db.sql_ddl(f'DROP INDEX IF EXISTS "{unique_index.Key_name}"')
                    except Exception as e:
                        if frappe.db.is_duplicate_fieldname(e):
                            continue
                        raise

class DmColumn(DbColumn):
    def get_definition(self, for_modification=False):
        column_def = get_definition(self.fieldtype, precision=self.precision, length=self.length)

        if not column_def:
            return column_def

        # 达梦数据库的CHECK约束语法
        if self.fieldtype in ("Check", "Int"):
            default_value = cint(self.default) or 0
            column_def += f" NOT NULL DEFAULT {default_value}"

        # 达梦数据库的浮点数默认值语法
        elif self.fieldtype in ("Currency", "Float", "Percent"):
            default_value = flt(self.default) or 0
            column_def += f" NOT NULL DEFAULT {default_value}"

        # 达梦数据库的字符串默认值语法
        elif (
            self.default
            and (self.default not in frappe.db.DEFAULT_SHORTCUTS)
            and not cstr(self.default).startswith(":")
        ):
            column_def += f" DEFAULT {frappe.db.escape(self.default)}"

        # 达梦数据库的唯一约束语法
        if self.unique and not for_modification and (column_def not in ("text", "longtext")):
            column_def += " UNIQUE"

        return column_def
